﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BEPUphysics.Entities;
using Microsoft.Xna.Framework;
using BEPUphysics;
using PloobsEngine.SceneControl;
using PloobsEngine.Modelo;

namespace PloobsEngine.Physics.Bepu
{
    public abstract class BepuEntityObject : IPhysicObject
    {
        public static IObject RecoverObjectFromEntity(BEPUphysics.Entities.Entity entity)
        {
            IPhysicObject phy = (entity.Tag as IPhysicObject);
            if (phy != null)
                return phy.ObjectOwner;
            return null;
        }

        public static IPhysicObject RecoverIPhysicObjectFromEntity(BEPUphysics.Entities.Entity entity)
        {
            return (entity.Tag as IPhysicObject);
        }


        public BepuEntityObject(float mass)
        {
            this.mass = mass;            
        }

        #region IPhysicObject Members

        protected BEPUphysics.Entities.Entity entity;
        protected float mass;
        private IObject obj;
        protected Vector3 scale = Vector3.One;

        public void LimitRotationAxis(bool x, bool y, bool z)
        {
            Matrix m = entity.LocalInertiaTensorInverse;
            if (!x)
            {
                m.M11 = 0;
                m.M12 = 0;
                m.M13 = 0;
                m.M14 = 0;
            }
            if (!y)
            {
                m.M21 = 0;
                m.M22 = 0;
                m.M23 = 0;
                m.M24 = 0;
            }
            if (!z)
            {
                m.M31 = 0;
                m.M32 = 0;
                m.M33 = 0;
                m.M34 = 0;
            }
            entity.LocalInertiaTensorInverse = m;
        }

        public BEPUphysics.Entities.Entity Entity
        {
            get { return entity; }
            set { entity = value; }
        }

        public virtual Microsoft.Xna.Framework.Vector3 Position
        {
            get
            {
                return entity.CenterPosition;
            }
            set
            {
                entity.CenterPosition = value;
            }
        }

        public virtual Microsoft.Xna.Framework.Vector3 Scale
        {
            get
            {
                return scale;
            }
            set
            {
                this.scale = value;
            }
        }

        public virtual Microsoft.Xna.Framework.Matrix Rotation
        {
            get
            {
                return entity.OrientationMatrix;
            }
            set
            {
                entity.OrientationMatrix = value;
            }
        }
        
        public virtual Microsoft.Xna.Framework.Vector3 FaceVector
        {
            get {
                return Rotation.Forward;                
            }
        }

        public virtual Microsoft.Xna.Framework.Matrix WorldMatrix
        {
            get {                  
                return Matrix.CreateScale(scale) * entity.WorldTransform ;               
            }
        }

        public virtual Microsoft.Xna.Framework.Vector3 Velocity
        {
            get
            {
                return entity.LinearVelocity;
            }
            set
            {
                this.entity.LinearVelocity = value;
            }
        }

        public virtual void Serialize(System.Xml.XmlTextWriter textWriter)
        {
            throw new NotImplementedException();
        }

        public virtual void DeSerialize(System.Xml.XmlNode node, EngineStuff engine, IModelo model, Microsoft.Xna.Framework.Vector3 position, Microsoft.Xna.Framework.Matrix rotation)
        {
            throw new NotImplementedException();
        }

        public virtual bool isMotionLess
        {
            get
            {
                return !entity.IsDynamic;
            }
            set
            {
                if (value == false)
                    this.entity.BecomeDynamic(mass);
                else
                    this.entity.BecomeKinematic();
            }
        }

        public IObject ObjectOwner
        {
            get
            {
                return obj;
            }
            set
            {
                this.obj = value;
                this.obj.OnBeingRemoved += new BeingRemoved(obj_OnBeingRemoved);    
            }
        }

        void obj_OnBeingRemoved(IObject obj)
        {
            if (entity != null)
                entity.EventManager.RemoveAllEvents();            
        }

        public abstract PhysicObjectTypes PhysicObjectTypes
        {
            get;            
        }


        public virtual void Enable()
        {
            entity.IsActive = true;
        }

        public virtual void Disable()
        {
            entity.IsActive = false;
        }

        public virtual void ApplyImpulse(Microsoft.Xna.Framework.Vector3 force)
        {            
            entity.ApplyImpulse(entity.CenterOfMass, force,true);
        }

        public virtual void ApplyTorque(Microsoft.Xna.Framework.Vector3 force)
        {
            Quaternion q =  Quaternion.CreateFromAxisAngle(Vector3.Up, force.Y);
            entity.ApplyQuaternion(ref q, true);
            //entity.AngularVelocity = force;            
            //entity.IsActive = true;
            //entity.ApplyAngularImpulse(force);
            //entity.ApplyImpulse(entity.CenterOfMass + force,force,true);
            
        }

        public virtual Microsoft.Xna.Framework.BoundingBox BoundingBox
        {
            get { return entity.BoundingBox; }
        }

        //public virtual void AddToWorld(Space space)
        //{
        //    space.Add(this.entity);
        //}

        #endregion
    }
}
